<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="/favicon.png" type="image/x-icon">
    <script src="/js/vue.min.js"></script>
    <script src="/js/tailwindcss.min.js"></script>
    <style>
        @keyframes dance {
            from {
                height: 0;
            }
            to {
                height: 40px;
            }
        }
        @keyframes rotate-cover {
            to {
                rotate: 360deg;
            }
        }
        .dance-box {
            animation: dance 500ms ease-in-out var(--delay) infinite alternate;
        }
        .cover-img {
            animation: rotate-cover 20s linear infinite;
            animation-play-state: paused;
            &.active {
                animation-play-state: running;
            }
        }
        .box-hidden-scrollbar {
            &::-webkit-scrollbar {
                display: none;
                width: 0;
            }
        }
    </style>
    <title>音乐播放</title>
</head>
<body>
    <div id="app" class="flex w-[900px] h-[600px] mx-auto mt-[50px] bg-blue-200 rounded-[20px] overflow-hidden shadow-[5px_5px_10px_#000]" v-show="list.length!==0">
        <div class="w-[300px] bg-red-200 p-[10px]">
            <ul class="flex flex-col gap-[10px] h-full overflow-auto box-hidden-scrollbar">
                <li v-for="item in list" :key="item.id" class="flex gap-[20px] rounded-[10px] items-center cursor-pointer p-[10px] relative" :class="currentId===item.id && 'bg-gray-200'" @click="handleClick(item.id)">
                    <img :src="item.imgUrl"class="size-[60px] rounded-[16px] select-none"/>
                    <div class="flex flex-col gap-[6px]">
                        <p class="select-none text-[18px] text-red-600 font-bold">{{ item.songName }}</p>
                        <p class="select-none text-[14px]">{{ item.singer }}</p>
                    </div>
                    <ul class="absolute right-[10px] size-[40px] flex justify-center gap-[4px] items-end" v-if="isPlaying && currentId===item.id">
                       <li class="w-[8px] h-0 bg-blue-600 dance-box" style="--delay: 100ms"></li> 
                       <li class="w-[8px] h-0 bg-blue-600 dance-box" style="--delay: 450ms"></li>
                       <li class="w-[8px] h-0 bg-blue-600 dance-box" style="--delay: 300ms"></li>
                       <li class="w-[8px] h-0 bg-blue-600 dance-box" style="--delay: 200ms"></li>
                    </ul>
                </li>
            </ul>
        </div>
        <div class="flex-1 flex flex-col items-center">
            <p class="text-[24px] mt-[30px] mb-[30px] select-none">{{ songName }} - {{ singer }}</p>
            <img :src="imgUrl" class="block size-[400px] rounded-full shadow-[0_0_20px_#f00] select-none cover-img" :class="isPlaying && 'active'"/>
            <div class="flex gap-[40px] mt-[30px]">
                <button class="bg-gray-700 active:bg-gray-800 select-none cursor-pointer text-[#fff] rounded-[8px] px-[12px] py-[6px]" @click="handlePrev">上一首</button>
                <button class="bg-gray-700 active:bg-gray-800 select-none cursor-pointer text-[#fff] rounded-[8px] px-[12px] py-[6px]" @click="handlePlay">{{ isPlaying ? '暂停' : '播放'}}</button>
                <button class="bg-gray-700 active:bg-gray-800 select-none cursor-pointer text-[#fff] rounded-[8px] px-[12px] py-[6px]" @click="handleNext">下一首</button>
            </div>
        </div>
        <audio ref="audio" class="hidden"></audio>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                currentId: -1,               // 当前播放项目的id
                list: [],                    // 歌曲数据
                isPlaying: false,            // 播放状态
            },
            async mounted() {               // 请求歌曲数据
                const response = await fetch('/songs');
                const json = await response.json();
                this.list = json.data;
                if (this.list.length===0) {
                    this.currentId = -1;
                } else {
                    this.currentId = this.list[0].id;
                    const audio = this.$refs.audio;
                    src = this.list[0].href;
                    // 监听播放停止事件
                    audio.addEventListener('ended', () => {
                        this.selectRandomSong();             // 随机播放另一首歌
                    });
                }
            },
            methods: {
                async selectRandomSong() {
                    // 暂停当前播放
                    const audio = this.$refs.audio;
                    this.isPlaying = false;
                    // 随机播放另一首歌
                    const index = Math.floor(this.list.length * Math.random());
                    this.currentId = this.list[index].id;
                    audio.src = this.list[index].href;
                    await audio.play();
                    this.isPlaying = true;
                },
                async handleClick(id) {
                    const index = this.list.findIndex(it => it.id===id);
                    this.currentId=id;
                    const audio = this.$refs.audio;
                    audio.src = this.list[index].href;
                    if (this.isPlaying) {
                        await audio.play();
                    }
                },
                async handlePlay() {
                    const audio = this.$refs.audio;
                    if (this.isPlaying) {
                        await audio.pause();
                    } else {
                        await audio.play();
                    }
                    this.isPlaying=!this.isPlaying;
                },
                async handlePrev() {
                    const index = this.list.findIndex(it => it.id===this.currentId);
                    const audio = this.$refs.audio;
                    if (index<1) {
                        // 取最后一项
                        this.currentId = this.list[this.list.length-1].id;
                        audio.src = this.list[this.list.length-1].href;
                        return;
                    }
                    this.currentId = this.list[index-1].id;
                    
                    audio.src = this.list[index-1].href;
                    if (this.isPlaying) {
                        await audio.play();
                    }
                },
                async handleNext() {
                    const index = this.list.findIndex(it => it.id===this.currentId);
                    const audio = this.$refs.audio;
                    if (index===this.list.length-1) {
                        // 取第一项
                        this.currentId = this.list[0].id;
                        audio.src = this.list[0].href;
                        return;
                    }
                    this.currentId = this.list[index+1].id;
                    
                    audio.src = this.list[index+1].href;
                    if (this.isPlaying) {
                        await audio.play();
                    }
                },
            },
            computed: {
                singer() {
                    if (this.list.length===0) return '';
                    const index = this.list.findIndex(it => it.id===this.currentId);
                    return this.list[index].singer;
                },
                songName() {
                    if (this.list.length===0) return '';
                    const index = this.list.findIndex(it => it.id===this.currentId);
                    return this.list[index].songName;
                },
                imgUrl() {
                    if (this.list.length===0) return '#';
                    const index = this.list.findIndex(it => it.id===this.currentId);
                    return this.list[index].imgUrl;
                }
            },
        });
    </script>
</body>
</html>